#!/usr/bin/env python 3.6
# -*- coding: utf-8 -*-
# @Time      :2019/2/14
# @Author    :Tian Maohong
# @Email     :tianmaohong@bbdservice.com
# @File      :R41_TX_EntAnnualValueAddedTaxAmtAnnualCheck_GZ
# @Software  :PyCharm


import json
import re
import sys
import datetime
import pandas as pd
import math

'''eof
name:企业纳税年均纳税额校验（年度汇算清缴表）
code:R41_TX_EntAnnualValueAddedTaxAmtAnnualCheck_GZ
tableName:
columnName:
groups:场景业务校验-税务
dependencies:TX_GZ_DSJ
type:常用指标
datasourceType:在线指标
description:
eof'''


# reload(sys)
# sys.setdefaultencoding('utf-8')


def inquireIsReportNo(data):
    """
    判断是否存在reportNo
    :param data:
    :return:True/False
    """
    try:

        is_reportNo = True if len(data.get("reportNo")) > 0 else False

    except:
        is_reportNo = False

    return is_reportNo


def formatData(table_Name):
    """
    获取数据
    :param table_Name:字典keys
    :return:[{}]
    """
    try:
        data = TX_GZ_DSJ["data"].get(table_Name)
        return data if isinstance(data, list) and len(data) > 0 else [{}]

    except:
        return [{}]

def dataPre(dataList=None, key=None):
    """
    对list里面的列表去重月份不标准的
    :param dataList:
    :param key:
    :return:
    """
    dataListTemp = dataList
    data = []
    for i in range(len(dataListTemp)):
        temp = dataListTemp[i].get(key)
        try:
            temp = int(temp)
        except:
            temp = None
            pass

        if temp:
            data.append(dataListTemp[i])
        else:
            pass

    if len(data) == 0:
        data = [{}]
    else:
        pass

    return data


def convertDataType(data_value, data_type):
    """
    数据格式转换
    :param data_value:
    :param data_type: float/int/str/date_time
    :return:
    """
    data_value = str(data_value)
    if data_value =="nan":
        return None
    return_data = None
    # float
    if data_type == 'float':
        try:
            return_data = float(data_value) if len(data_value) >= 0 else None
        except:
            return_data = None
    # int
    elif data_type == 'int':
        try:
            return_data = int(data_value) if len(data_value) >= 0 else None
        except:
            return_data = None
    # str
    elif data_type == 'str':
        try:
            return_data = str(data_value) if len(data_value) >= 0 else None
        except:
            return_data = None
    # date_time
    elif data_type == 'date_time':
        r = re.compile(r'\D+')
        try:
            return_data = datetime.datetime.strptime(data_value, '%Y.%m.%d').strftime('%Y-%m-%d')
        except:
            try:
                return_data = datetime.datetime.strptime(data_value, '%Y-%m-%d').strftime('%Y-%m-%d')
            except:
                try:
                    return_data = datetime.datetime.strptime(data_value, '%Y/%m/%d').strftime('%Y-%m-%d')
                except:
                    try:
                        data_value = r.sub('', data_value)
                        return_data = datetime.datetime.strptime(data_value, '%Y%m%d').strftime('%Y-%m-%d')
                    except:
                        return_data = None

    return return_data


def vatDataMerge(syptZzsxgm, syptZzsybnsr, putBackYear=2, CcrDate=None):
    """
    增值税纳税数据拆分为近两年的月度数据

    :param syptZzsxgm:小规模增值税纳税表[{}]；
    :param syptZzsybnsr:一般纳税人增值税表[{}]；
    :param putBackYear:回推时间，默认为2年；
    :param CcrDate:测试时间，默认为None，格式为datetime.date(2019, 2, 19)；
    :return: VatData为Series
    """
    # 字典排序
    syptZzsxgm = dataPre(syptZzsxgm, key='YF')
    syptZzsybnsr = dataPre(syptZzsybnsr, key='YF')


    # 生成时间轴
    dateIndexList = []
    if CcrDate is None:
        CcrYearMonth = datetime.datetime.now().strftime('%Y-%m-%d')[:7]
        CcrDate = CcrYearMonth + '-01'
        StartDateTmp = str(datetime.datetime.now().year - putBackYear) + CcrDate[4:]
        StartDate = StartDateTmp[:7] + '-01'
    else:
        CcrYear = datetime.datetime.strptime(convertDataType(CcrDate, 'date_time'), '%Y-%m-%d').date().year
        CcrDate = convertDataType(CcrDate, 'date_time')[:7] + '-01'
        StartDate = str(CcrYear - putBackYear) + convertDataType(CcrDate, 'date_time')[4:]

    dateSet = pd.date_range(StartDate, CcrDate, freq='M')
    for i in dateSet:
        year = i.date().year
        month = i.date().month
        dateIndexList.append(str(year) + str(month))

    VatData = pd.Series(None, index=dateIndexList)

    if syptZzsxgm == [{}] and syptZzsybnsr == [{}]:
        return VatData
    else:
        # 一般纳税人
        if syptZzsybnsr != [{}]:
            syptZzsybnsr = sorted(syptZzsybnsr, key=lambda x: int(x['YF']))
            for i in range(len(syptZzsybnsr)):
                ND = convertDataType(syptZzsybnsr[i].get('ND'), 'int')
                YF = convertDataType(syptZzsybnsr[i].get('YF'), 'int')
                if ND and YF:
                    NDYF = str(ND) + str(YF)
                    if NDYF in VatData.index:
                        YNSEHJ = convertDataType(syptZzsybnsr[i].get('YNSEHJ'), 'float')
                        if YNSEHJ:
                            if math.isnan(VatData.loc[str(ND) + str(YF)]):
                                VatData.loc[str(ND) + str(YF)] = YNSEHJ
                            else:
                                pass
                        else:
                            pass
                    else:
                        pass
                else:
                    pass

        # 小规模纳税人
        if syptZzsxgm != [{}]:
            syptZzsxgm = sorted(syptZzsxgm, key=lambda x: int(x['YF']))
            for i in range(len(syptZzsxgm)):
                ND = convertDataType(syptZzsxgm[i].get('ND'), 'int')
                YF = convertDataType(syptZzsxgm[i].get('YF'), 'int')
                if ND and YF:
                    NDYF = str(ND) + str(YF)
                    if NDYF in VatData.index:
                        YNSEHJDBNBQ = convertDataType(syptZzsxgm[i].get('YNSEHJDBNBQ'), 'float')
                        if YNSEHJDBNBQ:
                            if YF not in [3, 6, 9, 12]:
                                if math.isnan(VatData.loc[str(ND)+str(YF)]):
                                    VatData.loc[str(ND)+str(YF)] = YNSEHJDBNBQ
                            else:
                                # 倒推三个月在时间轴内
                                if str(ND) + str(YF) in VatData.index and str(ND) + str(YF-1) in VatData.index and\
                                        str(ND) + str(YF-2) in VatData.index:

                                    # 临近三个月全为空，3个为空
                                    if math.isnan(VatData.loc[str(ND) + str(YF)]) \
                                            and math.isnan(VatData.loc[str(ND) + str(YF - 1)])\
                                            and math.isnan(VatData.loc[str(ND) + str(YF - 2)]):
                                        VatData.loc[str(ND) + str(YF)] = YNSEHJDBNBQ / 3
                                        VatData.loc[str(ND) + str(YF - 1)] = YNSEHJDBNBQ / 3
                                        VatData.loc[str(ND) + str(YF - 2)] = YNSEHJDBNBQ / 3
                                    # 临近三个月倒数第3个月非空，2个为空
                                    elif math.isnan(VatData.loc[str(ND) + str(YF - 1)]) and \
                                            not math.isnan(VatData.loc[str(ND) + str(YF - 2)]):
                                        VatData.loc[str(ND) + str(YF - 1)] = YNSEHJDBNBQ / 2
                                        VatData.loc[str(ND) + str(YF)] = YNSEHJDBNBQ / 2
                                    # 临近三个月倒数第2个月非空，2个为空
                                    elif math.isnan(VatData.loc[str(ND) + str(YF - 2)]) and \
                                        not math.isnan(VatData.loc[str(ND) + str(YF - 1)]):
                                        VatData.loc[str(ND) + str(YF - 2)] = YNSEHJDBNBQ / 2
                                        VatData.loc[str(ND) + str(YF)] = YNSEHJDBNBQ / 2
                                    # 临近三个月倒数第三个月非空，1个为空
                                    elif not math.isnan(VatData.loc[str(ND) + str(YF - 2)]) and \
                                        not math.isnan(VatData.loc[str(ND) + str(YF - 1)]) \
                                            and math.isnan(VatData.loc[str(ND) + str(YF)]):
                                        VatData.loc[str(ND) + str(YF)] = YNSEHJDBNBQ
                                # 倒数最后YF-2月不在时间轴内
                                elif str(ND) + str(YF-2) not in VatData.index and\
                                        str(ND) + str(YF-1) in VatData.index and\
                                        str(ND) + str(YF) in VatData.index:
                                    # 倒推两个月都为空
                                    if math.isnan(VatData.loc[str(ND) + str(YF)]) and math.isnan(VatData.loc[str(ND) + str(YF-1)]):
                                        VatData.loc[str(ND) + str(YF)] = YNSEHJDBNBQ / 3
                                        VatData.loc[str(ND) + str(YF - 1)] = YNSEHJDBNBQ / 3
                                    elif math.isnan(VatData.loc[str(ND) + str(YF-1)]):
                                        VatData.loc[str(ND) + str(YF)] = YNSEHJDBNBQ / 2
                                # 倒数YF-1月不在时间轴内
                                elif str(ND) + str(YF - 2) not in VatData.index and\
                                        str(ND) + str(YF - 1) not in VatData.index and\
                                        str(ND) + str(YF) in VatData.index:
                                    if math.isnan(VatData.loc[str(ND) + str(YF)]):
                                        VatData.loc[str(ND) + str(YF)] = YNSEHJDBNBQ / 3
                        else:
                            pass
                    else:
                        pass
                else:
                    pass

    return VatData



def incomeTaxDataMerge(syptQysdsNd, CcrDate=None):
    """
    所得税纳税数据拆分为近2年的只有年度汇算清缴

    :param syptQysdsNd: 年度汇算清缴表，类型[{}]
    :return: IncomeTaxData为Series
    """

    syptQysdsNd = dataPre(syptQysdsNd, key='ND')

    if syptQysdsNd == [{}]:
        YNSDSELastOne, YNSDSELastTwo = 0, 0
        return YNSDSELastOne, YNSDSELastTwo
    else:
        # 使用年度汇算清缴表
        if syptQysdsNd != [{}]:
            syptQysdsNd = sorted(syptQysdsNd, key=lambda x: int(x['ND']))
            if CcrDate is None:
                CcrMonth = datetime.datetime.now().month
                CcrYear = datetime.datetime.now().year
            else:
                CcrDate = datetime.datetime.strptime(convertDataType(CcrDate, 'date_time'), '%Y-%m-%d').date()
                CcrYear = CcrDate.year
                CcrMonth = CcrDate.month

            syptQysdsNd = pd.DataFrame(syptQysdsNd)

            if CcrMonth > 5:
                if str(CcrYear - 1) in list(syptQysdsNd['ND']):
                    # 去空以后如果还在里面，取对应的数值；若不在则置0
                    try:
                        syptQysdsNdTemp = syptQysdsNd.dropna(how="all")
                        YNSDSELastOne = convertDataType(syptQysdsNdTemp[syptQysdsNdTemp['ND'] ==
                                                                        str(CcrYear - 1)]['YNSDSE'].iloc[-1], 'float')
                    except:
                        YNSDSELastOne = 0
                else:
                    YNSDSELastOne = 0

                if str(CcrYear - 2) in list(syptQysdsNd['ND']):
                    # 去空以后如果还在里面，取对应的数值；若不在则置0
                    try:
                        syptQysdsNdTemp = syptQysdsNd.dropna(how="all")
                        YNSDSELastTwo = convertDataType(syptQysdsNdTemp[syptQysdsNdTemp['ND'] ==
                                                                        str(CcrYear - 2)]['YNSDSE'].iloc[-1], 'float')
                    except:
                        YNSDSELastTwo = 0
                else:
                    YNSDSELastTwo = 0
            else:
                if str(CcrYear - 1) in list(syptQysdsNd['ND']):
                    # 去空以后如果还在里面，取对应的数值；若不在则置0
                    try:
                        syptQysdsNdTemp = syptQysdsNd.dropna(how="all")
                        YNSDSELastOne = convertDataType(syptQysdsNdTemp[syptQysdsNdTemp['ND'] ==
                                                                    str(CcrYear - 1)]['YNSDSE'].iloc[-1], 'float')
                    except:
                        YNSDSELastOne = 0

                    if str(CcrYear - 2) in list(syptQysdsNd['ND']):
                        # 去空以后如果还在里面，取对应的数值；若不在则置0
                        try:
                            syptQysdsNdTemp = syptQysdsNd.dropna(how="all")
                            YNSDSELastTwo = convertDataType(syptQysdsNdTemp[syptQysdsNdTemp['ND'] ==
                                                                            str(CcrYear - 2)]['YNSDSE'].iloc[-1], 'float')
                        except:
                            YNSDSELastTwo = 0

                    else:
                        YNSDSELastTwo = 0

                else:
                    if str(CcrYear - 2) in list(syptQysdsNd['ND']):
                        # 去空以后如果还在里面，取对应的数值；若不在则置0
                        try:
                            syptQysdsNdTemp = syptQysdsNd.dropna(how="all")
                            YNSDSELastOne = convertDataType(syptQysdsNdTemp[syptQysdsNdTemp['ND'] ==
                                                                        str(CcrYear - 2)]['YNSDSE'].iloc[-1], 'float')
                        except:
                            YNSDSELastOne = 0
                    else:
                        YNSDSELastOne = 0

                    if str(CcrYear - 3) in list(syptQysdsNd['ND']):
                        # 去空以后如果还在里面，取对应的数值；若不在则置0
                        try:
                            syptQysdsNdTemp = syptQysdsNd.dropna(how="all")
                            YNSDSELastTwo = convertDataType(syptQysdsNdTemp[syptQysdsNdTemp['ND'] ==
                                                                            str(CcrYear - 3)]['YNSDSE'].iloc[-1], 'float')
                        except:
                            YNSDSELastTwo = 0
                    else:
                        YNSDSELastTwo = 0


            return YNSDSELastOne, YNSDSELastTwo


def entAnnualTaxAmtAnnualCheck(spDate=None):
    """
    企业年均纳税额校验（年度汇算清缴表）
    :return:
    """

    syptZzsxgm = formatData('syptZzsXgm')
    syptZzsybnsr = formatData('syptZzsybnsr')

    # 增值税数据合并
    if syptZzsybnsr == [{}] and syptZzsxgm == [{}]:
        return -0.001
    else:
        vatDataSeries = vatDataMerge(syptZzsxgm=syptZzsxgm, syptZzsybnsr=syptZzsybnsr, CcrDate=spDate)
        vatDataSeries = vatDataSeries.fillna(value=0)

        lastOneVatSum = sum(vatDataSeries[-12:]) * 0.65
        lastTwoVatSum = sum(vatDataSeries[:12]) * 0.35
        VatSum = lastOneVatSum + lastTwoVatSum

        return round(VatSum, 4)


result = entAnnualTaxAmtAnnualCheck()

#
# try:
#     if __name__ == '__main__':
#         # 下面添加需要执行的函数
#         # 读取json文件
#         file_obj = open(r'G:\\BBDWork\\project\\modelMigration\\data\\TX_CQ_DSJ.js', 'r')
#         content = file_obj.read()
#         TX_CQ_DSJ = json.loads(content, strict=False)['TX_CQ_DSJ']
#
#         # 审批时间
#         spDateTime = '20180812'
#
#         # 连续性纳税校验
#         aa = entAnnualTaxAmtAnnualCheck()
#         # aa = entAnnualTaxAmtAnnualCheck(spDate=spDateTime)
#         pass
# except Exception as e:
#     print('exception happen')
#     raise e